WoMax Documentation OMax Logo

PPC/bc.yinstats.c

00001 /*--------------------------------------
00002  * bc.stat - bc.stat.c
00003  * Created on 24/11/09 by Benjamin Levy
00004  *--------------------------------------*/
00005 
00006 
00007 #include "ext.h"                                // standard Max include, always required
00008 #include "ext_obex.h"                   // required for new style Max object
00009 #include "ext_time.h"
00010 #include "ext_itm.h"
00011 
00012 
00013 typedef struct _statelem
00014         {
00015                 bool    enable;
00016                 long    pitch;
00017                 double  nbOcc;
00018                 double  nbtot;
00019                 double  ampacc;
00020                 double  proba;
00021                 void*   clock;
00022                 void*   object;
00023         } bc_statelem;
00024 
00025 
00027 typedef struct _bc_yinstats 
00028         {
00029                 t_object                ob;                             // the object itself (must be first)
00030                 long                    nbstats;                // number of stat agent
00031                 bc_statelem*    stats;                  // stat agent vector
00032                 double                  minproba;               // minimal probabilty
00033                 long                    window;                 // window for stats (ms)
00034                 double                  lastpitch;              // last pitch
00035                 double                  lastamp;                // last amplitude
00036                 long                    laststat;               // last stat enable
00037                 void*                   out_pitch;              // outlet 0
00038                 void*                   out_amp;                // outlet 1
00039                 void*                   out_proba;              // outlet 2
00040         } t_bc_yinstats;
00041 
00043 // prototypes //
00045 
00046 // Standard Max5 methodes
00047 void *bc_yinstats_new(t_symbol *s, long argc, t_atom *argv);
00048 void bc_yinstats_free(t_bc_yinstats *x);
00049 void bc_yinstats_assist(t_bc_yinstats *x, void *b, long m, long a, char *s);
00050 
00051 // Input/ouput routines
00052 void bc_yinstats_amp(t_bc_yinstats *x, double ampin);
00053 void bc_yinstats_pitch(t_bc_yinstats *x, long pitchin);
00054 void bc_yinstats_out(bc_statelem *stat);
00055 void bc_yinstats_stop(t_bc_yinstats *x);
00056 
00057 // Internal routines
00058 bool bc_yinstats_addocc(t_bc_yinstats *x, long pitchin, double ampin);
00059 long bc_yinstats_addstat(t_bc_yinstats *x, long pitchin, double ampin);
00060 void bc_yinstats_reset(t_bc_yinstats *x, bc_statelem *stat);
00061 
00062 // Global class pointer variable
00063 void *bc_yinstats_class;
00064 
00065 
00066 int main(void)
00067 {       
00068         t_class *c;
00069         
00070         c = class_new("bc.yinstats", (method)bc_yinstats_new, (method)bc_yinstats_free, (long)sizeof(t_bc_yinstats), 0L, A_GIMME, 0);
00071         
00072         // assistance
00073     class_addmethod(c, (method)bc_yinstats_assist,"assist",A_CANT, 0); 
00074         
00075         // input methods
00076         class_addmethod(c, (method)bc_yinstats_pitch, "int", A_LONG, 0);
00077         class_addmethod(c, (method)bc_yinstats_amp, "ft1", A_FLOAT, 0);
00078         class_addmethod(c, (method)bc_yinstats_stop, "stop", 0);
00079                 
00080         CLASS_ATTR_LONG(c, "window", 0, t_bc_yinstats, window);
00081         CLASS_ATTR_LABEL(c, "window", 0, "Window (ms)");
00082         CLASS_ATTR_SAVE(c, "window", 0);
00083         CLASS_ATTR_MIN(c, "window", 0, 0);
00084         
00085         CLASS_ATTR_DOUBLE(c, "minproba", 0, t_bc_yinstats, minproba);
00086         CLASS_ATTR_LABEL(c, "minproba", 0, "Probability Threshold");
00087         CLASS_ATTR_SAVE(c, "minproba", 0);
00088         CLASS_ATTR_FILTER_CLIP(c, "minproba", 0., 1.);
00089         
00090         class_register(CLASS_BOX, c); /* CLASS_NOBOX */
00091         bc_yinstats_class = c;
00092         
00093         return 0;
00094 }
00095 
00096 // Object instantiation
00097 void *bc_yinstats_new(t_symbol *s, long argc, t_atom *argv)
00098 {
00099         t_bc_yinstats *x = NULL;
00100         
00101         // object instantiation, NEW STYLE
00102         if (x = (t_bc_yinstats *)object_alloc(bc_yinstats_class))
00103         {
00104                 // inlets
00105                 floatin(x, 1); // amplitude
00106                 
00107                 // outlets
00108                 x->out_proba = floatout(x);
00109                 x->out_amp = floatout(x);
00110                 x->out_pitch = intout(x);
00111                 
00112                 x->nbstats = 100;
00113                 x->minproba = 0.;
00114                 
00115                 // process arguments
00116                 switch (argc)
00117                 {
00118                         /*
00119                         case 3:
00120                                 if ((argv + 2)->a_type == A_FLOAT);
00121                                         x->minproba = atom_getfloat(argv + 2);
00122                         case 2:
00123                                 if ((argv + 1)->a_type == A_LONG);
00124                                         x->window = atom_getlong(argv + 1);
00125                          */
00126                         case 1:
00127                                 if (argv->a_type == A_LONG)
00128                                         x->nbstats = atom_getlong(argv);
00129                                 break;
00130                         default:
00131                                 object_error((t_object *)x, "Number of stat agents needed");
00132                 }
00133                 
00134                 // process attributes
00135                 // override arguments if needed
00136                 attr_args_process(x, argc, argv);
00137                 
00138                 x->stats = (bc_statelem*)sysmem_newptr(x->nbstats * sizeof(bc_statelem));
00139                 long i;
00140                 for (i = 0; i< x->nbstats; i++)
00141                         bc_yinstats_reset(x, x->stats + i);             
00142                 x->laststat = 0;
00143         }
00144         return (x);
00145 }
00146 
00147 // Object destruction
00148 void bc_yinstats_free(t_bc_yinstats *x)
00149 {
00150         long i;
00151         for (i = 0; i< x->nbstats; i++)
00152         {
00153                 freeobject(x->stats[i].clock);
00154         }
00155         sysmem_freeptr(x->stats);
00156 }
00157 
00158 // Inlet/Outlet contextual information when patching in Max5
00159 void bc_yinstats_assist(t_bc_yinstats *x, void *b, long io, long index, char *s)
00160 {
00161         switch (io)
00162         {
00163                 case 1: // inlets
00164                         switch (index)
00165                 {
00166                         case 0: // leftmost
00167                                 sprintf(s, "pitch");
00168                                 break;
00169                         case 1:
00170                                 sprintf(s, "amplitude");
00171                                 break;
00172                 }
00173                         break;
00174                 case 2: // outlets
00175                         switch (index)
00176                 {
00177                         case 0: // leftmost
00178                                 sprintf(s, "coocked pitch");
00179                                 break;
00180                         case 1: 
00181                                 sprintf(s, "average amplitude");
00182                                 break;
00183                         case 2:
00184                                 sprintf(s,"probability");
00185                                 break;
00186                 }
00187         }
00188 }
00189 
00190 void bc_yinstats_amp(t_bc_yinstats *x, double ampin)
00191 {
00192         x->lastamp = ampin;
00193 }
00194 
00195 void bc_yinstats_pitch(t_bc_yinstats *x, long pitchin)
00196 {
00197         x->lastpitch = pitchin;
00198         bc_yinstats_addocc(x, pitchin, x->lastamp);
00199         bc_yinstats_addstat(x, pitchin, x->lastamp);
00200 }
00201 
00202 bool bc_yinstats_addocc(t_bc_yinstats *x, long pitchin, double ampin)
00203 {
00204         long i;
00205         bool found = FALSE;
00206         for (i = 0; i<=(x->laststat); i++)
00207         {
00208                 if (x->stats[i].enable)
00209                 {
00210                         x->stats[i].nbtot++;
00211                         if (x->stats[i].pitch == pitchin)
00212                         {
00213                                 found = TRUE;
00214                                 x->stats[i].nbOcc++;
00215                                 x->stats[i].ampacc += ampin;
00216                         }
00217                 }
00218         }
00219         return found;   
00220 }
00221 
00222 long bc_yinstats_addstat(t_bc_yinstats *x, long pitchin, double ampin)
00223 {
00224         long i = 0;
00225         while (x->stats[i].enable && i<x->nbstats)
00226                 i++;
00227         if (i == x->nbstats)
00228         {
00229                 i = 0;
00230                 object_error((t_object *)x, "too many events");
00231         }
00232         x->stats[i].enable = TRUE;
00233         x->stats[i].pitch = pitchin;
00234         x->stats[i].ampacc = ampin;
00235         x->stats[i].nbOcc = 1;
00236         x->stats[i].nbtot = 1;
00237         clock_delay(x->stats[i].clock, x->window);
00238         if (i > (x->laststat))
00239                 x->laststat = i;
00240         return i;
00241 }
00242 
00243 void bc_yinstats_reset(t_bc_yinstats *x, bc_statelem *stat) 
00244 {
00245         stat->enable = FALSE;
00246         stat->pitch = 0;
00247         stat->ampacc = 0.;
00248         stat->nbOcc = 0;
00249         stat->nbtot = 0;
00250         stat->proba = 0.;
00251         stat->object = x;
00252         stat->clock = clock_new(stat , (method)bc_yinstats_out);
00253 }
00254 
00255 void bc_yinstats_out(bc_statelem *stat)
00256 {
00257         t_bc_yinstats * x = stat->object;
00258         stat->proba = stat->nbOcc / stat->nbtot;
00259         if (stat->proba >= x->minproba)
00260         {
00261                 outlet_float(x->out_proba, stat->proba);
00262                 outlet_float(x->out_amp, stat->ampacc / stat->nbOcc);
00263                 outlet_int(x->out_pitch, stat->pitch);
00264         }
00265         stat->enable = FALSE;
00266 }
00267 
00268 void bc_yinstats_stop(t_bc_yinstats *x)
00269 {
00270         long i;
00271         for (i = 0; i< x->laststat; i++)
00272         {
00273                 x->stats[i].enable = FALSE;
00274                 clock_unset(x->stats[i].clock);
00275         }
00276         x->laststat = 0;
00277 }

Generated on 16 Mar 2010 for Benjamin Lévy by  doxygen 1.6.1